using System;

namespace SmartBoard.Core.Data
{
    public abstract class BoardElementDataManagerBase:IBoardElementDataManager
    {
        #region Fields
        protected readonly IDataVersionConverter _versionConverter;
        #endregion

        #region Ctor
        protected BoardElementDataManagerBase(IDataVersionConverter versionConverter)
        {
            _versionConverter = versionConverter;
        }
        #endregion

        #region Implementation of IBoardElementDataManager

        public IBoardElementData GetData()
        {
            var elementData = DoGetData();

            if (elementData == null || elementData.Version == this.CurrentDataVersion)
            {
                return elementData;
            }
            else
            {
                if (_versionConverter.CanConvert(elementData.Version, this.CurrentDataVersion))
                {
                    return _versionConverter.Convert(elementData, this.CurrentDataVersion);
                }
                else
                {
                    throw new FormatException("the format is not supported");
                }
            }
        }

        public void SetData(IBoardElementData data)
        {
            if (data == null || data.Version == this.ElementDataVersion)
            {
                DoSetData(data);
            }
            else
            {
                if (_versionConverter.CanConvert(data.Version, this.ElementDataVersion))
                {
                    var convertedData = _versionConverter.Convert(data, this.ElementDataVersion);
                    this.CurrentDataVersion = data.Version;
                    DoSetData(convertedData);
                }
                else
                {
                    throw new FormatException("the format is not supported");
                }
            }
        }

        public byte CurrentDataVersion
        {
            get; private set;
        }
        #endregion

        #region Abstract methods
        public abstract bool IsDataChanged { get; }
        public abstract byte ElementDataVersion { get; }
        protected abstract IBoardElementData DoGetData();
        protected abstract void DoSetData(IBoardElementData data);
        #endregion
    }
}